home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / console / svgatext.3 / svgatext / SVGATextMode-1.3 / setclock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  7.7 KB  |  276 lines

  1. /*  SVGATextMode -- An SVGA textmode manipulation/enhancement tool
  2.  *
  3.  *  Copyright (C) 1995,1996  Koen Gadeyne
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20.  
  21. /***
  22.  *** main SVGA clock programming functions for SVGATextMode
  23.  ***/
  24.  
  25. #include <stdio.h>
  26. #include <unistd.h>
  27. #ifndef DOS
  28. #  include <asm/io.h>
  29. #endif
  30. #include <math.h>
  31. #include "misc.h"
  32. #include "vga_prg.h"
  33. #include "wait_vsync.h"
  34. #include "setclock.h"
  35. #include "std_clock.h"
  36. #include "clockchip.h"
  37. #include "messages.h"  
  38. #include "run_extprog.h"  
  39.  
  40.  
  41. /*****************************************************************************************************************************/
  42.  
  43. void clock_check(int result)
  44. {
  45.   if (result < 0)
  46.   {
  47.     switch(result)
  48.     {
  49.       case CLKSEL_DONOTHING:     PWARNING(("Clock selection: Warning: Clock not changed\n"));
  50.                                  break;
  51.       case CLKSEL_ILLEGAL_NUM:   PERROR(("Clock selection: illegal clock number.\n"));
  52.                                  break;
  53.       case CLKSEL_NULLCLOCK:     PERROR(("Clock selection: 0 MHz clock selected! It would lock up the video card. Aborting...\n"));
  54.                                  break;
  55.       case CLKSEL_OUT_OF_BOUNDS: PERROR(("Clock selection: Requested clock frequency out of bounds\n"));
  56.                                  break;
  57.       default: PERROR(("Clock selection: unknown error\n"));
  58.     }
  59.   }
  60. }
  61.  
  62.  
  63. int findclosestclock(int req_clock, int *closest_clock)
  64. {
  65.    /* returns closest clock NUMBER when one is found, error code otherwise */
  66.  
  67.    int i, closest=0;
  68.    int num=clock_data.num_clocks;
  69.  
  70.    *closest_clock = req_clock;  /* start with both equal */
  71.  
  72.    if (req_clock == 0) return(CLKSEL_NULLCLOCK);
  73.    
  74.    /* create 1/2 clocks when option is set */
  75.    if (OFLG_ISSET(OPT_CLOCKDIV2))
  76.    {
  77.      for (i=0; i<num; i++) clock_data.clocks[i+num] = clock_data.clocks[i]/2;
  78.      num *= 2;
  79.    }
  80.  
  81.    /* for (i=0; i<num; i++) PDEBUG(("CLOCK #%d = %d\n",i, clock_data.clocks[i])); */
  82.    
  83.    /* find closest clock frequency */
  84.    for (i=0 ; i < num ; i ++)
  85.    {
  86.       if ( abs(clock_data.clocks[i] - req_clock) < abs(clock_data.clocks[closest] - req_clock) ) { closest = i; }
  87.    }
  88.  
  89.    *closest_clock = clock_data.clocks[closest];
  90.    PDEBUG(("findclosestclock: closest clock nr %d = %d kHz.\n",closest, *closest_clock));
  91.    if (closest>clock_data.num_clocks)
  92.      PDEBUG((" (clock index #%d is actually index #%d divided by 2)\n", closest, closest-clock_data.num_clocks));
  93.    
  94.    if (closest < 0) return(CLKSEL_DONOTHING);
  95.    if (closest > num) return(CLKSEL_ILLEGAL_NUM);
  96.    if (*closest_clock == 0) return(CLKSEL_NULLCLOCK);
  97.    
  98.    return(closest);
  99. }
  100.  
  101.  
  102. int GetClock(int chipset, int freq, int *closestfreq, int report_error)
  103.  /* look for correct clock index (for indexed clock chips), and check for out-of-bound clocks */
  104. {
  105.    int result;
  106.    
  107.    switch(chipset)
  108.    {
  109.      case CS_CIRRUS: /* should do some range checking here */
  110.                      result = 0; /* suppose it can make any frequency */
  111.                      break;
  112.      default: result = findclosestclock(freq, closestfreq);
  113.    }
  114.    if (report_error) clock_check(result);
  115.    return(result);
  116. }
  117.  
  118.  
  119.  
  120. void SetClock(int chipset, int freq)
  121. {
  122.    int result, divby2=0;
  123.    
  124.    result = GetClock(chipset, freq, &freq, TRUE);
  125.   /* clock number is supposed to be in the allowable range by now.
  126.      error checking should have been done before.
  127.      No error checking will be done in clock-setting routine! */
  128.      
  129.    if (OFLG_ISSET(OPT_CLOCKDIV2) && (result > clock_data.num_clocks-1))
  130.    {
  131.       divby2 = 1;
  132.       result -= clock_data.num_clocks; /* make clock selection routine pick the real clock (before division by 2) */
  133.    }
  134.  
  135.    PDEBUG(("Setting Clock to %d kHz\n", freq));
  136.    SYNCRESET_SEQ;
  137.    switch(chipset)
  138.    {
  139.      case CS_VGA:
  140.         SET_CLOCKBITS_0_1(result);
  141.         break;
  142.      case CS_CIRRUS:
  143.         CirrusClockSelect(freq);
  144.         break;
  145.      case CS_S3:
  146.         s3ClockSelect(result);
  147.         break;
  148.      case CS_ET4000:
  149.         ET4000ClockSelect(result);
  150.         break;
  151.      case CS_ET3000:
  152.         ET3000ClockSelect(result);
  153.         break;
  154.      case CS_TVGA8900:
  155.      case CS_TVGA9000:
  156.         TVGAClockSelect(chipset, clock_data.num_clocks, result);
  157.         break;
  158.      case CS_PVGA1:
  159.      case CS_WDC90C0X:
  160.      case CS_WDC90C1X:
  161.      case CS_WDC90C2X:
  162.      case CS_WDC90C3X:
  163.         WDCClockSelect(chipset, clock_data.num_clocks, result);
  164.         break;
  165.      case CS_ATI:
  166.      case CS_ATIMACH32:
  167.         ATIClockSelect(chipset, result);
  168.         break;
  169.      case CS_VIDEO7:
  170.         Video7ClockSelect(result);
  171.         break;
  172.      case CS_ALI:
  173.      case CS_AL2101:
  174.         ALIClockSelect(chipset, result);
  175.         break;
  176.      case CS_OTI67:
  177.      case CS_OTI77:
  178.      case CS_OTI87:
  179.         OAKClockSelect(chipset, result);
  180.         break;
  181.      case CS_SIS:
  182.         SISClockSelect(result);
  183.         break;
  184.      case CS_REALTEK:
  185.         RealTekClockSelect(result);
  186.         break;
  187.      case CS_ARK:
  188.         ARKClockSelect(result);
  189.         break;
  190.      case CS_NCR22E:
  191.      case CS_NCR32:
  192.         NCRClockSelect(chipset, result);
  193.         break;
  194.      case CS_GVGA:
  195.         GVGAClockSelect(result);
  196.         break;
  197.      case CS_MX:
  198.         MXClockSelect(result);
  199.         break;
  200.      default: PERROR(("Internal error in setclock.c: unknown chip set #%d\n", chipset));
  201.    }
  202.  
  203.    if (OFLG_ISSET(OPT_CLOCKDIV2))
  204.    {
  205.       Outbit_SEQ(1,3,divby2);
  206.       if (divby2) PDEBUG(("Clock (%d) needed 'division by 2' feature.\n", freq));
  207.    }
  208.    else
  209.    {
  210.       /* disable ClockDiv2 always */
  211.       Outbit_SEQ(1,3,0);
  212.    }
  213.  
  214.    ENDRESET_SEQ;
  215.    usleep(50000); /* let PLL clock synthesizer stabilize */
  216.    clock_check(result);
  217. }
  218.  
  219.  
  220. /*****************************************************************************************************************************/
  221.  
  222. void do_clock(int chipset, int clock)
  223. {
  224.   char tempstr[1024]="";
  225.  
  226.   /* program clocks in V-blanking only, avoiding video memory corruption and system hangs (?) */
  227.  
  228.   safe_wait_vsync(); /* wait for VSYNC... if there is one */
  229.   SCREEN_OFF;
  230.  
  231.   /* mclk programming */
  232.   if (clock_data.mclk != MCLK_NOT_DEFINED)
  233.   {
  234.     if (clock_data.clockchiptype != CLKCHIP_NONE)
  235.     {
  236.       switch(clock_data.clockchiptype)
  237.       {
  238.         case CLKCHIP_S3_SDAC:
  239.         case CLKCHIP_S3GENDAC:
  240.         case CLKCHIP_ICS5300:
  241.         case CLKCHIP_ICS5342:
  242.         case CLKCHIP_ICS5341:
  243.              set_clockchip_Mclock(chipset, clock_data.mclk);
  244.              break;
  245.         default: PERROR(("mclk programming not supported on selected Clock chip\n"));
  246.       }
  247.       PMESSAGE(("Setting mclk to %d kHz\n", clock_data.mclk));
  248.     }
  249.     else PERROR(("mclk programming not supported for non-clockchip VGA cards\n"));
  250.   }
  251.  
  252.   safe_wait_vsync(); /* wait for VSYNC... if there is one */
  253.   
  254.   /* PixClock programming */
  255.   if (clock_data.ck_prog_path)
  256.   {
  257.      int clockindex = 0;
  258.      /* find clock index in clocks line */
  259.      clockindex = GetClock(chipset, clock, &clock, TRUE);
  260.      sprintf(tempstr,"%s %1.3f %d", clock_data.ck_prog_path, clock/1000.0, clockindex);
  261.      SYNCRESET_SEQ;
  262.      Run_extern_Prog(tempstr);
  263.      ENDRESET_SEQ;
  264.   }
  265.   else
  266.     if (clock_data.clockchiptype != CLKCHIP_NONE)
  267.       set_clockchip_clock(chipset, clock);
  268.   else
  269.   {
  270.     SetClock(chipset, clock);
  271.   }
  272.   SCREEN_ON;
  273. }
  274.  
  275.  
  276.